#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
@date: 2011-11-12
@author: shell.xu
'''
import os, sys, logging
import xapian
import config, segment, html2text
from os import path
from bson.objectid import ObjectId

def atcdoc(cols, aid):
    ''' article到doc对象的相关代码
    给予一个集合，一个aid，返回三个函数
    * 分别负责将这个article转换为doc对象，如果无需索引，返回None
    * 获得这个article对应的did，如果没有，返回None
    * 设定这个article对应的did '''
    atc = cols.find_one({'_id': ObjectId(aid)})

    def todoc():
        posting = {}
        if not hasattr(config, 'seg'):
            config.seg = segment.get_cutter(config.segdbname)
        for t in config.seg.parse(html2text.html2text(atc['content'])):
            if t not in posting: posting[t] = 0
            posting[t] += 1
        if not posting: return None

        doc = xapian.Document()
        doc.set_data(str(aid))
        for k, v in posting.items(): doc.add_posting(k, v)
        return doc

    def getdid(): return atc.get('did', None)

    def setdid(did):
        atc['did'] = did
        logging.debug('%s set docid %d' % (atc['_id'], atc['did']))
        cols.save(atc)

    return todoc, getdid, setdid

def xapian_env(name, middoc):
    ''' xapian操作的相关代码
    给予一个mongo database对象，索引基础目录，mongodb的数据集名称，数据集到doc的相关代码，返回三个函数
    * 更新xapian index，给予mongo数据集的id，添加或者更新该id对应的数据到xapian中
    * 删除xapian index，给予xapian docid，删除该id对应的xapian doc
    * 检索xapian index，给予搜索条件，结果offset和limit，返回对应的did, rank, mongo id列表
    '''
    cols = config.db[name]
    xdb = xapian.WritableDatabase(path.join(config.idxpath, name),
                                  xapian.DB_CREATE_OR_OPEN)

    def update(mid):
        logging.info('%s update %s' % (name, mid))
        todoc, getdid, setdid = middoc(cols, mid)
        doc = todoc()
        if doc is None: return
        if getdid() is None: setdid(xdb.add_document(doc))
        else: xdb.replace_document(getdid(), doc)
        xdb.flush()
        return True

    def remove(did):
        logging.info('delete %s' % did)
        xdb.delete_document(did)
        xdb.flush()
        return True

    def search(query, offset, limit):
        qp = xapian.QueryParser()
        qp.set_database(xdb)
        enquire = xapian.Enquire(xdb)
        enquire.set_query(qp.parse_query(query))
        matches = enquire.get_mset(offset, limit)
        rslt = [(m.docid, m.rank, m.document.get_data()) for m in matches]
        return matches.get_matches_estimated(), rslt

    return update, remove, search
